/*************************************************************************
> File Name: analyse.c
> Author: hzy
> Created Time: 2023-09-25 10:33:07
> Description:
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <unistd.h>

int main(int argc, char const *argv[])
{
    // 创建套接字
    int sock_raw = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sock_raw < 0)
    {
        perror("socket");
        exit(-1);
    }

    while (1)
    {
        sleep(1);
        // 接受数据
        unsigned char buf[1500] = {0};
        recvfrom(sock_raw, buf, sizeof(buf), 0, NULL, NULL);

        // 解析数据包
        // 数据包发给谁的
        unsigned char dest_mac[20] = {0};
        sprintf(dest_mac,
                "%02x:%02x:%02x:%02x:%02x:%02x",
                buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);

        // 数据包谁发的
        unsigned char src_mac[20] = {0};
        sprintf(src_mac,
                "%02x:%02x:%02x:%02x:%02x:%02x",
                buf[0 + 6], buf[1 + 6], buf[2 + 6], buf[3 + 6], buf[4 + 6], buf[5 + 6]);
        // printf("dest_mac:%s -> src_mac:%s\n", dest_mac, src_mac);
        unsigned short type = ntohs(*(unsigned short *)(buf + 12));
        if (type == 0x0800)
        {
            // IP报文
            unsigned char *ip_buf = buf + 14; // 跳过MAC头部

            unsigned char ip_type = ip_buf[9]; // 得到上一层数据协议的类型

            unsigned char dest_ip[16] = {};
            unsigned char src_ip[16] = {};

            unsigned short ip_head_len = ((ip_buf[0] & 0x0f) * 4); // 获取ip报文的首部长度

            inet_ntop(AF_INET, ip_buf + 12, src_ip, sizeof(src_ip));   // 获取源ip地址
            inet_ntop(AF_INET, ip_buf + 16, dest_ip, sizeof(dest_ip)); // 获取目标ip地址
            printf("-------------------IP-------------------\n");
            printf("dest_mac:%s -> src_mac:%s\n", dest_mac, src_mac);
            printf("dest_ip:%s -> src_ip:%s\n\n", dest_ip, src_ip);

            if (ip_type == 1)
            {
                printf("-------------------ICMP-------------------\n");
            }
            else if (ip_type == 2)
            {
                printf("-------------------IGMP-------------------\n");
            }
            else if (ip_type == 6)
            {
                printf("-------------------TCP-------------------\n");
                unsigned char *tcp_buf = buf + 14 + ip_head_len;
                unsigned short tcp_src_port = ntohs(*(unsigned short *)(tcp_buf + 0));  // 获取源端口号
                unsigned short tcp_dest_port = ntohs(*(unsigned short *)(tcp_buf + 2)); // 获取目的端口号
                printf("src_port:%d -> dest_src:%d\n\n", tcp_src_port, tcp_dest_port);
            }
            else if (ip_type == 17)
            {
                printf("-------------------UDP-------------------\n");
                unsigned char *udp_buf = buf + 14 + ip_head_len;
                unsigned short udp_src_port = ntohs(*(unsigned short *)(udp_buf + 0));  // 获取源端口号
                unsigned short udp_dest_port = ntohs(*(unsigned short *)(udp_buf + 2)); // 获取目的端口号
                printf("src_port:%d -> dest_src:%d\n\n", udp_src_port, udp_dest_port);
            }
        }
        else if (type == 0x0806)
        {
            // ARP请求/应答
        }
        else if (type == 0x8035)
        {
            // RARP请求/应答
        }
    }
    return 0;
}